package com.easylinkin.linkappapi.facerecognition.service.oss.impl;


import com.easylinkin.linkappapi.facerecognition.dto.OSSPolicy;
import com.easylinkin.linkappapi.facerecognition.service.oss.ObjectStorageOutsideService;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidArgumentException;
import io.minio.errors.InvalidBucketNameException;
import io.minio.errors.InvalidExpiresRangeException;
import io.minio.errors.MinioException;
import io.minio.errors.NoResponseException;
import io.minio.messages.Item;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.xmlpull.v1.XmlPullParserException;

public class MinIoObjectStorageService implements ObjectStorageOutsideService {

    private static final Logger log = LoggerFactory.getLogger(MinIoObjectStorageService.class);

    private final MinioClient minioClient;

    public MinIoObjectStorageService(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    @Override
    public void createBucket(String bucketName) {
        try {
            boolean found = checkBucketExist(bucketName);

            if (!found) {
                // 创建存储空间
                minioClient.makeBucket(bucketName);
                log.info("Create MinIO oss bucket " + bucketName);
            }
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException | XmlPullParserException e) {
            log.error("Create MinIO oss bucket error : " + bucketName, e);
        }

    }

    @Override
    public boolean checkBucketExist(String bucketName) {

        try {
            return minioClient.bucketExists(bucketName);
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException | XmlPullParserException e) {
            log.error("Check MinIO oss bucket exist error : " + bucketName, e);
        }
        return false;
    }

    /**
     * MinIO 中不需要单独的创建文件夹，它会自动的创建文件路径中的目录
     * */
    @Override
    public void createFolder(String bucketName, String folder) {
        throw new UnsupportedOperationException("No need to create folder.");
    }

    @Override
    public boolean checkObjectExist(String bucketName, String objectName) {

        try {

            String folder = "";
            int lastIndex = objectName.lastIndexOf("/");
            if (lastIndex != -1) {
                folder = objectName.substring(0, lastIndex);
            }

            Iterable<Result<Item>> items;
            if ("".equals(folder)) {
                items = minioClient.listObjects(bucketName);
            } else {
                items = minioClient.listObjects("test");
            }

            for (Result<Item> item : items) {
                if (objectName.equals(item.get().objectName())) {
                    return true;
                }
            }
        } catch (XmlPullParserException | InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | InvalidKeyException | ErrorResponseException | IOException | NoResponseException | InternalException e) {
            log.error("Check object exist MinIO oss error " + objectName, e);
        }

        return false;
    }

    @Override
    public void deleteFile(String bucketName, String objectName) {

        try {
            minioClient.removeObject(bucketName, objectName);
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Delete file MinIO oss error " + objectName, e);
        }
    }

    @Override
    public String generatePresignedUrl(String bucketName, String objectName, int expiry) {
        try {
            return minioClient.presignedGetObject(bucketName, objectName, expiry);
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InvalidExpiresRangeException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Generate url MinIO oss error " + objectName , e);
        }

        return null;
    }

    @Override
    public void uploadImgObject(String bucketName, String file, InputStream is) {

        try {
            // 上传文件 (上传文件流的形式)
            minioClient.putObject(bucketName, file, is, is.available(), "image/jpeg");
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InvalidArgumentException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Upload object MinIO oss error " + file, e);
        }
    }


    @Override
    public InputStream getObjectInputStream(String bucketName, String objectName) {
        try {
            return minioClient.getObject(bucketName, objectName);
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InvalidArgumentException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Get Object InputStream MinIO oss error " + objectName, e);
        }

        return null;
    }

    @Override
    public void copyObject(String bucketName, String objectName, String destBucketName, String destObjectName) {
        try {
            minioClient.copyObject(bucketName, objectName, destBucketName, destObjectName);
        } catch (InvalidKeyException | InsufficientDataException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidArgumentException | InvalidBucketNameException | ErrorResponseException | InternalException | IOException e) {
            log.error("Copy Object MinIO oss error " + objectName, e);
        }
    }

    @Override
    public void putObject(String bucketName, String objectName, InputStream in) {
    }

    @Override
    public void putObject(String bucketName, String objectName, InputStream in,
        String contentType) {
        try {
            minioClient.putObject(bucketName,objectName,in,contentType);
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InvalidArgumentException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Upload object MinIO oss error " + objectName, e);
        }
    }

    @Value("${minio.uploadHost:/api/oss/uploadMinio}")
    private String uploadHost;

    /** 查看地址 */
    @Value("${minio.uploadHost:/api/oss/download}")
    private String accessHost;

    public String getUploadHost() {
        return uploadHost;
    }

    public void setUploadHost(String uploadHost) {
        this.uploadHost = uploadHost;
    }

    public String getAccessHost() {
        return accessHost;
    }

    public void setAccessHost(String accessHost) {
        this.accessHost = accessHost;
    }

    @Override
    public OSSPolicy generatePostPolicy(String dir) {
      OSSPolicy p = new OSSPolicy();
      p.setAccessId("");
      p.setPolicy("minio");
      p.setSignature("");
      p.setUploadHost(uploadHost);
      p.setAccessHost(accessHost);
      p.setPath(dir);
      return p;
    }

    @Override
    public void uploadFile(String bucket, MultipartFile multipartFile, String fileName) {
        String contentType = multipartFile.getContentType();
        try {
            // 上传文件 (上传文件流的形式)
            minioClient.putObject(bucket,fileName,multipartFile.getInputStream(),contentType);
        } catch (InvalidKeyException | NoSuchAlgorithmException | NoResponseException | XmlPullParserException | InvalidBucketNameException | InvalidArgumentException | InsufficientDataException | ErrorResponseException | InternalException | IOException e) {
            log.error("Upload object MinIO oss error " + fileName, e);
        }

    }
}
